/*******************************************************************************
 * Copyright (c) 2008-2009 zhang yuexiang.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package org.xfeep.asura.bootstrap.test;


import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.xfeep.asura.core.ComponentDefinition;
import org.xfeep.asura.core.ServiceSpace;
import org.xfeep.asura.bootstrap.Asura;
import org.xfeep.asura.bootstrap.MemoryComponentLoader;
import org.xfeep.asura.bootstrap.PackageBundleComponentLoader;
import org.xfeep.asura.bootstrap.SimpleComponentLoader;
import org.xfeep.asura.bootstrap.XmlComponentLoader;
import org.xfeep.asura.core.config.ConfigAdminService;
import org.xfeep.asura.core.console.CommandLineService;
import org.xfeep.asura.core.logger.CoreLoggerManager;
import org.xfeep.asura.core.util.InlineExecutorService;

import static junit.framework.Assert.*;

public class AsuraDefaultBootTestSet {

	Asura asura;
	
	@Before
	public void setUp() throws Exception {
		asura = new Asura(); //new URLClassLoader(new URL[]{new File("bin").toURI().toURL()})
		asura.setExecutorService(new InlineExecutorService());
	}

	@Test
	public void testLoadDefaultServices() throws ClassNotFoundException {
		long ss = System.currentTimeMillis();
		asura.start();
		System.out.println("MeomoryComponentLoader cost: " + (System.currentTimeMillis() - ss) + "ms");
		assertTrue(asura.isStarted());
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		appServiceSpace.findService(ConfigAdminService.class).put("test", new HashMap<String, Object>());
		String[] componentNames = MemoryComponentLoader.getCoreComponentList();
		for (String name : componentNames){
			ComponentDefinition cd = ComponentDefinition.create(this.getClass().getClassLoader().loadClass(name));
			for (Class<?> service : cd.getInterfaces()){
				System.out.println(service.getName());
				assertNotNull(appServiceSpace.findService(service));
			}
		}
	}
	
	@Test
	public void testSimpleLoader() throws Throwable {
		long ss = System.currentTimeMillis();
		asura.start(new SimpleComponentLoader(this.getClass().getResource("asura_component_list")));
		System.out.println("SimpleComponentLoader cost: " + (System.currentTimeMillis() - ss) + "ms");
		
		assertTrue(asura.isStarted());
		
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		appServiceSpace.findService(ConfigAdminService.class).put("test", new HashMap<String, Object>());
		String[] componentNames = MemoryComponentLoader.getCoreComponentList();
		for (String name : componentNames){
			ComponentDefinition cd = ComponentDefinition.create(this.getClass().getClassLoader().loadClass(name));
			for (Class<?> service : cd.getInterfaces()){
				assertNotNull(appServiceSpace.findService(service));
			}
		}
	}
	
//	@Test
//	public void testXmlComponentDefinition() throws Exception{
//		JAXBContext jaxbContext;
//		jaxbContext = JAXBContext.newInstance(CompositeDefinitionInfo.class);
//		CompositeDefinitionInfo compositeDefinitionInfo = new CompositeDefinitionInfo("test");
//		ComponentDefinitionInfo gcdi = ComponentDefinitionInfo.convert(ComponentDefinition.create(GrizzlyHttpService.class));
//		compositeDefinitionInfo.components.add(gcdi);
////		JAXBElement<ComponentDefinitionInfo> je = new JAXBElement(
////				  new QName("","rootTag"), ComponentDefinitionInfo.class, cdi);
//		Marshaller m = jaxbContext.createMarshaller();
//		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//		m.marshal(compositeDefinitionInfo, System.out);
//
//	}

//	@Test
//	public void testXmlComonentExport() throws IOException, JAXBException {
//		SimpleComponentLoader simpleComponentLoader = new SimpleComponentLoader();
//		List<ComponentDefinition> list = simpleComponentLoader.getStaticLoadComponents(this.getClass().getClassLoader());
//		CompositeDefinitionInfo compositeDefinitionInfo = new CompositeDefinitionInfo("core");
//		for (ComponentDefinition cd : list){
//			compositeDefinitionInfo.components.add( ComponentDefinitionInfo.convert(cd) );
//		}
//		JAXBContext jaxbContext = JAXBContext.newInstance(CompositeDefinitionInfo.class);
//		Marshaller m = jaxbContext.createMarshaller();
//		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//		m.marshal(compositeDefinitionInfo, new File("asura_core_composite-full.xml"));
//	}
//	
//	@Test
//	public void testXmlComonentExportShortly() throws IOException, JAXBException {
//		SimpleComponentLoader simpleComponentLoader = new SimpleComponentLoader();
//		List<ComponentDefinition> list = simpleComponentLoader.getStaticLoadComponents(this.getClass().getClassLoader());
//		CompositeDefinitionInfo compositeDefinitionInfo = new CompositeDefinitionInfo("core");
//		for (ComponentDefinition cd : list){
//			compositeDefinitionInfo.components.add( ComponentDefinitionInfo.convert(cd, true) );
//		}
//		JAXBContext jaxbContext = JAXBContext.newInstance(CompositeDefinitionInfo.class);
//		Marshaller m = jaxbContext.createMarshaller();
//		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
////		System.setProperty(XmlComponentLoader.COMPOSITE_XML, "");
//		m.marshal(compositeDefinitionInfo, new File(XmlComponentLoader.getCompositeXmlFile()));
//	}
	
	@Test
	public void testXmlComonentLoader() throws IOException, ClassNotFoundException {
		

		long ss = System.currentTimeMillis();
		asura.start(new XmlComponentLoader(this.getClass().getResource("asura_core_composite.xml")));
		System.out.println("XmlComponentLoader cost: " + (System.currentTimeMillis() - ss) + "ms");
		
		assertTrue(asura.isStarted());
		
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		appServiceSpace.findService(ConfigAdminService.class).put("test", new HashMap<String, Object>());

		
		String[] componentNames = MemoryComponentLoader.getCoreComponentList();
		for (String name : componentNames){
			ComponentDefinition cd = ComponentDefinition.create(this.getClass().getClassLoader().loadClass(name));
			for (Class<?> service : cd.getInterfaces()){
				assertNotNull(appServiceSpace.findService(service));
			}
		}
		
	}

	@Test
	public void testLoadFromClassPath() throws ClassNotFoundException {
		long ss = System.currentTimeMillis();
		List<File> libraryFiles = new ArrayList<File>();
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		while (loader != null){
			if (loader instanceof URLClassLoader) {
				URLClassLoader urlClassLoader = (URLClassLoader) loader;
				for (URL url : urlClassLoader.getURLs()){
					try {
						File f = new File(url.toURI());
						libraryFiles.add(f);
					} catch (URISyntaxException e) {
						CoreLoggerManager.getDefaultLogger().warn("parse library file fail, the url is " + url , e);
					}
				}
			}
			loader = loader.getParent();
		}
		PackageBundleComponentLoader[] clds = new PackageBundleComponentLoader[libraryFiles.size()];
		for (int i = 0; i < clds.length; i++){
			clds[i] = new PackageBundleComponentLoader(libraryFiles.get(i));
		}
		asura.start(clds);
		asura.addComponentsFormLoaders(new MemoryComponentLoader(CommandLineService.class));
		System.out.println("PackageBundleComponentLoader cost: " + (System.currentTimeMillis() - ss) + "ms");
		
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		appServiceSpace.findService(CommandLineService.class).printServices();
		appServiceSpace.findService(ConfigAdminService.class).put("test", new HashMap<String, Object>());

		
		String[] componentNames = MemoryComponentLoader.getCoreComponentList();
		for (String name : componentNames){
			ComponentDefinition cd = ComponentDefinition.create(this.getClass().getClassLoader().loadClass(name));
			for (Class<?> service : cd.getInterfaces()){
				assertNotNull(appServiceSpace.findService(service));
			}
		}
	}
	
	@After
	public void tearDown() throws Exception {
		asura.shutdown();
	}

}
